package net.vkits.auth.application;

import net.vkits.auth.domain.model.Role;
import net.vkits.auth.domain.model.User;
import net.vkits.auth.domain.repository.RoleRepository;
import net.vkits.auth.domain.repository.UserRepository;
import net.vkits.common.exceptions.NoSuchUserException;
import net.vkits.common.exceptions.ValueAbsentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;

/**
 * Created by ethan-liu on 16/3/20.
 */
@Service
public class UserApplicationService {
    private static final Logger logger = LoggerFactory.getLogger(UserApplicationService.class);

    @Resource
    private UserRepository userRepository;

    @Resource
    private RoleRepository roleRepository;

    @Transactional
    public void addUser(String username, String password) {
        User user = new User(username, password);
        userRepository.save(user);
    }

    @Transactional
    public void changePassword(String username, String newPassword) throws ValueAbsentException {
        Optional<User> userOptional = userRepository.findByUsername(username);
        userOptional.ifPresent(user -> {
            user.changePassword(newPassword);
            userRepository.save(user);
        });
        userOptional.orElseThrow(NoSuchUserException::new);
    }

    @Transactional
    public void resetPassword(String username) {
        Optional<User> userOptional = userRepository.findByUsername(username);
        userOptional.ifPresent(user -> {
            user.changePassword("123456");
            userRepository.save(user);
        });
        userOptional.orElseThrow(NoSuchUserException::new);
    }

    @Transactional
    public void deleteUser(String username) {
        Optional<User> userOptional = userRepository.findByUsername(username);
        userOptional.ifPresent(user -> {
            user.deletedUser();
            userRepository.save(user);
        });
        userOptional.orElseThrow(NoSuchUserException::new);
    }

    @Transactional
    public void setAdminUser(String username) {
        Optional<User> userOptional = userRepository.findByUsername(username);
        userOptional.ifPresent(user -> {
            user.setAdmin();
            userRepository.save(user);
        });
        userOptional.orElseThrow(NoSuchUserException::new);
    }


    @Transactional
    public void setUserRole(String username, Set<String> roleIds) {
        Optional<User> userOptional = userRepository.findByUsername(username);
        userOptional.ifPresent(user -> {
            Set<Role> roles = new LinkedHashSet<Role>();
            roleIds.forEach(id ->
                            roles.add(roleRepository.findOne(Long.parseLong(id)))
            );
            user.setRoles(roles);
            userRepository.save(user);
        });
        userOptional.orElseThrow(NoSuchUserException::new);
    }

    public Page<User> getUserList(Pageable pageable) {
        return userRepository.findByDeletedFalse(pageable);
    }
}
